package org.abettor.nookinfo.view;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Matrix;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.os.SystemClock;
import android.util.AttributeSet;
import android.view.KeyEvent;
import android.view.animation.Animation;
import android.view.animation.TranslateAnimation;
import android.widget.ImageView;

/**
 * 用来缓存图片的类,抄的源码
 * 
 * @author jzh
 * 
 */
public abstract class ImageViewTouchBase extends ImageView {
	protected Matrix mBaseMatrix = new Matrix();// 基准图片的matrix
	protected Matrix mSuppMatrix = new Matrix();// 进行额外操作时的matrix
	protected Matrix mDisplayMatrix = new Matrix();// 显示图片时的matrix
	protected Bitmap mBitmapDisplayed;// 正在显示的图片
	private Bitmap mFullBitmap;
	int mThisWidth = -1, mThisHeight = -1;// 当前绘制图片的宽度和高度
	private float[] mMatrixValues = new float[9];// 用来临时获得matrix的值的数组
	float mMaxZoom;// 允许放大的最大倍数
	static final float sScaleRate = 1.25F;

	public ImageViewTouchBase(Context context, AttributeSet attrs) {
		super(context, attrs);
		setScaleType(ImageView.ScaleType.MATRIX);
	}

	public ImageViewTouchBase(Context context) {
		super(context);
		setScaleType(ImageView.ScaleType.MATRIX);
	}

	// 进行layout的操作
	@Override
	protected void onLayout(boolean changed, int left, int top, int right,
			int bottom) {
		super.onLayout(changed, left, top, right, bottom);
		mThisWidth = right - left;
		mThisHeight = bottom - top;
		// 延迟运行setImageBitmapResetBase的操作
		Runnable r = mOnLayoutRunnable;
		if (r != null) {
			mOnLayoutRunnable = null;
			r.run();
		}
		if (mBitmapDisplayed != null) {
			setBaseMatrix(mBitmapDisplayed, mBaseMatrix);
			setImageMatrix(getImageViewMatrix());
			mMaxZoom = maxZoom();
		}
	}

	/**
	 * 获得当前需要显示的matrix
	 * 
	 * @return
	 */
	protected Matrix getImageViewMatrix() {
		mDisplayMatrix.set(mBaseMatrix);
		mDisplayMatrix.postConcat(mSuppMatrix);
		return mDisplayMatrix;
	}

	@Override
	public boolean onKeyDown(int keyCode, KeyEvent event) {
		if (keyCode == KeyEvent.KEYCODE_BACK && getScale() > 1.0f) {
			// If we're zoomed in, pressing Back jumps out to show the entire
			// image, otherwise Back
			// returns the user to the gallery.
			zoomTo(1.0f);
			return true;
		}
		return super.onKeyDown(keyCode, event);
	}

	protected Handler mHandler = new Handler();// 用来进行异步操作的handler

	/**
	 * 进行动画性质的缩放工作
	 * 
	 * @param scale
	 * @param centerX
	 * @param centerY
	 * @param durationMs
	 */
	protected void zoomTo(final float scale, final float centerX,
			final float centerY, final float durationMs) {
		final float incrementPerMs = (scale - getScale()) / durationMs;
		final float oldScale = getScale();
		final long startTime = System.currentTimeMillis();
		mHandler.post(new Runnable() {
			@Override
			public void run() {
				long now = System.currentTimeMillis();
				float currentMs = Math.min(durationMs,
						(float) (now - startTime));
				float target = oldScale + (incrementPerMs * currentMs);
				zoomTo(target, centerX, centerY);

				if (currentMs < durationMs) {
					mHandler.post(this);
				}
			}
		});
	}

	/**
	 * 进行移位的操作
	 * 
	 * @param dx
	 * @param dy
	 */
	protected void panBy(final float dx,final float dy,final float durationMs) { 
		final float increX = (dx) /durationMs;
		final float increY = (dy) / durationMs;
		final long startTime = System.currentTimeMillis();
		mHandler.post(new Runnable(){
			float tmpx =0,tmpy = 0;
			@Override
			public void run() {
				long now = System.currentTimeMillis();
				float currentMs = Math.min(durationMs, now - startTime);
				float distanceX = increX*currentMs;
				float distanceY = increY*currentMs;
				postTranslate(distanceX-tmpx,distanceY-tmpy);
				tmpx = distanceX;
				tmpy = distanceY;
				setImageMatrix(getImageViewMatrix());
				if(currentMs < durationMs){
					mHandler.postDelayed(this, 10);
				}
			}
		});
	}
	/**
	 * 进行移位的操作
	 * 
	 * @param dx
	 * @param dy
	 */
	protected void panBy(final float dx,final float dy,final float durationMs,final Runnable run) {
		final float increX = dx /durationMs;
		final float increY = dy / durationMs;
		final long startTime = System.currentTimeMillis();
		mHandler.post(new Runnable(){
			@Override
			public void run() {
				long now = System.currentTimeMillis();
				float currentMs = Math.min(durationMs, (float)(now - startTime));
				postTranslate(increX*currentMs,increY*currentMs);
				setImageMatrix(getImageViewMatrix());
				if(currentMs < durationMs){
					mHandler.post(this);
				}else{
					mHandler.post(run);
				}
			}
		});
	}
	/**
	 * 放大图片
	 * 
	 * @param scale
	 * @param centerX
	 * @param centerY
	 */
	protected void zoomTo(float scale, float centerX, float centerY) {
		if (scale > mMaxZoom) {
			scale = mMaxZoom;
		}
		onZoom();
		float oldScale = getScale();
		float deltaScale = scale / oldScale;
		mSuppMatrix.postScale(deltaScale, deltaScale, centerX, centerY);
		setImageMatrix(getImageViewMatrix());
		center(true, true, false);
	}

	/**
	 * 设置背景的图片
	 */
	@Override
	public void setImageBitmap(Bitmap bitmap) {
		super.setImageBitmap(bitmap);
		Drawable d = getDrawable();
		if (d != null)
			d.setDither(true);
		mBitmapDisplayed = bitmap;
	}

	private Runnable mOnLayoutRunnable = null;

	/**
	 * 重新设置图片
	 * 
	 * @param bitmap
	 * @param resetSupp
	 */
	public void setImageBitmapResetBase(final Bitmap bitmap,
			final boolean resetSupp) {
		int viewWidth = getWidth();
		if (viewWidth <= 0) {// 当在没有初始化之前调用
			mOnLayoutRunnable = new Runnable() {
				public void run() {
					setImageBitmapResetBase(bitmap, resetSupp);// 延迟运行
				}
			};
			return;
		}
		if (mFullBitmap != null) {
			mFullBitmap.recycle();
		}
		mFullBitmap = bitmap;
		if (bitmap != null) {
			setScaleType(ImageView.ScaleType.MATRIX);
			setBaseMatrix(bitmap, mBaseMatrix);
			setImageBitmap(bitmap);
		} else {
			mBaseMatrix.reset();
			setImageBitmap(null);
		}
		if (resetSupp)
			mSuppMatrix.reset();
		setImageMatrix(getImageViewMatrix());
		mMaxZoom = maxZoom();
	}

	// 设置基本matrix,使bitmap好居中对齐
	private void setBaseMatrix(Bitmap bitmap, Matrix matrix) {
		if (bitmap == null) {
			return;
		}
		float viewWidth = getWidth();
		float viewHeight = getHeight();

		matrix.reset();
		float widthScale = Math
				.min(viewWidth / (float) bitmap.getWidth(), 1.0f);
		float heightScale = Math.min(viewHeight / (float) bitmap.getHeight(),
				1.0f);
		float scale;
		if (widthScale > heightScale) {
			scale = heightScale;
		} else {
			scale = widthScale;
		}
		matrix.setScale(scale, scale);
		matrix.postTranslate(
				(viewWidth - ((float) bitmap.getWidth() * scale)) / 2F,
				(viewHeight - ((float) bitmap.getHeight() * scale)) / 2F);
	}

	/**
	 * 显示原图片的大小
	 */
	protected void revertSize() {
		if (mBitmapDisplayed == null) {
			return;
		}
		float viewWidth = getWidth();
		float viewHeight = getHeight();
		float widthScale = Math.min(viewWidth
				/ (float) mBitmapDisplayed.getWidth(), 1.0f);
		float heightScale = Math.min(viewHeight
				/ (float) mBitmapDisplayed.getHeight(), 1.0f);
		float scale;// 放大的倍数
		if (widthScale > heightScale) {
			scale = heightScale;
		} else {
			scale = widthScale;
		}
		// 进行放大的操作
		zoomTo(1 / scale);
	}

	/**
	 * 获得可以放大的最大倍数
	 * 
	 * @return
	 */
	protected float maxZoom() {
		if (mBitmapDisplayed == null) {
			return 1f;
		}
		float fw = (float) mBitmapDisplayed.getWidth() / (float) mThisWidth;
		float fh = (float) mBitmapDisplayed.getHeight() / (float) mThisHeight;
		float max = Math.max(fw, fh) * 4;
		return max;
	}

	/**
	 * 移位操作
	 * 
	 * @param dx
	 * @param dy
	 */
	protected void postTranslate(float dx, float dy) {
		mSuppMatrix.postTranslate(dx, dy);
	}

	protected void zoomIn() {
		zoomIn(sScaleRate);
	}

	// 把图片置于中间
	protected void center(boolean vertical, boolean horizontal, boolean animate) {
		if (mBitmapDisplayed == null)
			return;
		Matrix m = getImageViewMatrix();
		float[] topLeft = new float[] { 0, 0 };
		float[] botRight = new float[] { mBitmapDisplayed.getWidth(),
				mBitmapDisplayed.getHeight() };

		translatePoint(m, topLeft);
		translatePoint(m, botRight);
		float height = botRight[1] - topLeft[1];
		float width = botRight[0] - topLeft[0];
		float deltaX = 0, deltaY = 0;
		if (vertical) {
			int viewHeight = getHeight();
			if (height < viewHeight) {
				deltaY = (viewHeight - height) / 2 - topLeft[1];
			} else if (topLeft[1] > 0) {
				deltaY = -topLeft[1];
			} else if (botRight[1] < viewHeight) {
				deltaY = getHeight() - botRight[1];
			}
		}

		if (horizontal) {
			int viewWidth = getWidth();
			if (width < viewWidth) {
				deltaX = (viewWidth - width) / 2 - topLeft[0];
			} else if (topLeft[0] > 0) {
				deltaX = -topLeft[0];
			} else if (botRight[0] < viewWidth) {
				deltaX = viewWidth - botRight[0];
			}
		}

		postTranslate(deltaX, deltaY);// 进行移位的操作
		if (animate) {
			Animation a = new TranslateAnimation(-deltaX, 0, -deltaY, 0);
			a.setStartTime(SystemClock.elapsedRealtime());
			a.setDuration(250);
			setAnimation(a);
		}
		setImageMatrix(getImageViewMatrix());
	}

	static private void translatePoint(Matrix matrix, float[] xy) {
		matrix.mapPoints(xy);
	}

	/**
	 * 进行移位的操作
	 * 
	 * @param dx
	 * @param dy
	 */
	protected void panBy(float dx, float dy) {
		postTranslate(dx, dy);
		setImageMatrix(getImageViewMatrix());
	}

	protected void zoomTo(float scale) {
		float width = getWidth();
		float height = getHeight();
		zoomTo(scale, width / 2F, height / 2F);
	}

	// 进行图片的缩小的操作
	protected void zoomOut(float rate) {
		if (mBitmapDisplayed == null) {
			return;
		}
		float width = getWidth();
		float height = getHeight();
		Matrix tmp = new Matrix(mSuppMatrix);
		tmp.postScale(rate, rate, width / 2F, height / 2F);
		if (getScale(tmp) < 1f) {
			mSuppMatrix.setScale(1F, 1F, width / 2F, height / 2F);
		} else {
			mSuppMatrix.setScale(1f / rate, 1f / rate, width / 2F, height / 2f);
		}
		setImageMatrix(getImageViewMatrix());
		center(true, true, false);
		onZoom();
	}

	// 放大的操作
	protected void zoomIn(float rate) {
		if (getScale() >= mMaxZoom) {
			return;
		}
		if (mBitmapDisplayed == null) {
			return;
		}
		float width = getWidth();
		float height = getHeight();
		mSuppMatrix.postScale(rate, rate, width / 2F, height / 2F);
		setImageMatrix(getImageViewMatrix());
		onZoom();
	}

	@Override
	public void setImageDrawable(android.graphics.drawable.Drawable d) {
		super.setImageDrawable(d);
	}

	public void onZoom() {
		if (mFullBitmap != null && mFullBitmap != mBitmapDisplayed) {
			setImageBitmapResetBase(mFullBitmap, false);
		}
	}

	protected float getScale(Matrix matrix) {
		return getValue(matrix, Matrix.MSCALE_X);
	}

	protected float getScale() {
		return getScale(mSuppMatrix);
	}

	protected float getValue(Matrix matrix, int whichValue) {
		matrix.getValues(mMatrixValues);
		return mMatrixValues[whichValue];
	}

	/**
	 * 获取图片对象
	 */
	public Bitmap getBitmap()
	{
		return mBitmapDisplayed;
	}
}
